//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "CombinedPatternsCathFASTAProfile.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fstream>
#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define MAX_SIZE             500000
#define LENGTHLINE           100000

#define CUOTE_ARFF           "\""

#define COMMENT_ARFF         "% "
#define RELATION_ARFF        "@relation "
#define DOMAIN_ATT_ARFF      "@attribute domain STRING"
#define PATTERN_ATT_ARFF     "@attribute \"%-s\" INTEGER\0"
#define PATTERN_ATT_COM_ARFF "@attribute \"%s.%-s\" INTEGER\0"
#define PATTERN_ATTN_ARFF    "@attribute \"%-s\" {yes, no}\0"
#define CLASS_ATT_ARFF       "@attribute class {bind, not-bind}"
#define DATA_ARFF            "@data"
#define VALUE_YES_ARFF       ",yes" 
#define VALUE_NO_ARFF        ",no" 
#define VALUE_BIND_ARFF      ",bind" 
#define VALUE_NBIND_ARFF     ",not-bind"

#define ATTRIBUTE_COMPLETE   1
#define PRINT_OUT            0
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
CombinedPatternsCathFASTAProfile::CombinedPatternsCathFASTAProfile (): PatternsCathFASTAProfile() {

  this->listPrattPatterns           = new TListE <Pratt2PatternsByCATH> ();
  this->listFilenamePatternsCompact = new TListE <String> ();
  this->listTypeOfData              = new TListE <String> ();

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
CombinedPatternsCathFASTAProfile::CombinedPatternsCathFASTAProfile (const CombinedPatternsCathFASTAProfile& combinedPatternsCathFASTAProfile): PatternsCathFASTAProfile(combinedPatternsCathFASTAProfile) {

  this->listPrattPatterns           = new TListE <Pratt2PatternsByCATH> (combinedPatternsCathFASTAProfile.listPrattPatterns);
  this->listFilenamePatternsCompact = new TListE <String> (combinedPatternsCathFASTAProfile.listFilenamePatternsCompact);
  this->listTypeOfData              = new TListE <String> (combinedPatternsCathFASTAProfile.listTypeOfData);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
CombinedPatternsCathFASTAProfile::CombinedPatternsCathFASTAProfile (const CombinedPatternsCathFASTAProfile* combinedPatternsCathFASTAProfile): PatternsCathFASTAProfile(combinedPatternsCathFASTAProfile) {

  this->listPrattPatterns           = new TListE <Pratt2PatternsByCATH> (combinedPatternsCathFASTAProfile->listPrattPatterns);
  this->listFilenamePatternsCompact = new TListE <String> (combinedPatternsCathFASTAProfile->listFilenamePatternsCompact);
  this->listTypeOfData              = new TListE <String> (combinedPatternsCathFASTAProfile->listTypeOfData);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
CombinedPatternsCathFASTAProfile::~CombinedPatternsCathFASTAProfile () {

  if (this->listPrattPatterns)           delete this->listPrattPatterns;
  if (this->listFilenamePatternsCompact) delete this->listFilenamePatternsCompact;
  if (this->listTypeOfData)              delete this->listTypeOfData;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void CombinedPatternsCathFASTAProfile::ListPrattPatterns (TListE <Pratt2PatternsByCATH>* listPrattPatterns) {

  if (listPrattPatterns)
    *(this->listPrattPatterns) = *listPrattPatterns;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void CombinedPatternsCathFASTAProfile::ListFilenamePatternsCompact (TListE <String>* listFilenamePatternsCompact) {

  if (listFilenamePatternsCompact)
    *(this->listFilenamePatternsCompact) = *listFilenamePatternsCompact;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void CombinedPatternsCathFASTAProfile::ListTypeOfData (TListE <String>* listTypeOfData) {

  if (listTypeOfData)
    *(this->listTypeOfData) = *listTypeOfData;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <Pratt2PatternsByCATH>* CombinedPatternsCathFASTAProfile::ListPrattPatterns (void) {

  return this->listPrattPatterns;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <String>* CombinedPatternsCathFASTAProfile::ListFilenamePatternsCompact (void) {

  return this->listFilenamePatternsCompact;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <String>* CombinedPatternsCathFASTAProfile::ListTypeOfData (void) {

  return this->listTypeOfData;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool CombinedPatternsCathFASTAProfile::LoadData (void) {

  if (!this->filenameCathFASTAProfile       || !this->filenameCathFASTAProfile->Length()       || 
      !this->filenameLigandCathFASTAProfile || !this->filenameLigandCathFASTAProfile->Length() || 
      !this->cathFASTAProfile               || !this->ligandCathFASTAProfile                   || 
      !this->prattPatterns                  || !this->listPrattPatterns                        || 
      !this->listFilenamePatternsCompact    || !this->listFilenamePatternsCompact->Length())
    return false;
  
  this->cathFASTAProfile->NamefileIn(this->filenameCathFASTAProfile);
  this->ligandCathFASTAProfile->NamefileIn(this->filenameLigandCathFASTAProfile);

  this->filenamePatternsCompact->In(this->listFilenamePatternsCompact->GetFirst());
  this->prattPatterns->Namefile(this->filenamePatternsCompact);
  
  this->cathFASTAProfile->LoadData();
  this->ligandCathFASTAProfile->LoadData();
  this->prattPatterns->LoadData();
  
  if (this->filenameExcludeCathFASTAProfile && this->filenameExcludeCathFASTAProfile->Length()) {
    this->excludeCathFASTAProfile->NamefileIn(this->filenameExcludeCathFASTAProfile);
    this->excludeCathFASTAProfile->LoadData();
  }
  
  this->listFilenamePatternsCompact->SetInitial();
  while (this->listFilenamePatternsCompact->SetNext()) {
    
    Pratt2PatternsByCATH* newPratt2PatternsByCATH = new Pratt2PatternsByCATH ();
    newPratt2PatternsByCATH->Namefile(this->listFilenamePatternsCompact->GetCurrent());
    
    if (newPratt2PatternsByCATH->LoadData())
      this->listPrattPatterns->Add(newPratt2PatternsByCATH);
    else
      delete newPratt2PatternsByCATH;
    
  }
  
  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool CombinedPatternsCathFASTAProfile::CreateCombinedARFF (String* nameRelation, String* comments, int positionInPatternFile, float percentagePattern, float percentageFalse) {

  if (!this->cathFASTAProfile     || !this->ligandCathFASTAProfile        || 
      !this->listPrattPatterns    || !this->listPrattPatterns->Length()   ||
      !this->filenameOut          || !this->filenameOut->Length()         || 
      (positionInPatternFile < 0))
    return false;
  
  ofstream fileARFF (this->filenameOut->Out());
  
  if (!fileARFF.is_open()) return false;
  
  char     buffer [LENGTHLINE + 1];
  char*    parts = NULL;
  
  strcpy (buffer, comments->Out());
  
  parts = strtok(buffer, "\n\r");
  while (parts) {
    fileARFF << COMMENT_ARFF << parts << endl;
    if (PRINT_OUT) 
      cout   << COMMENT_ARFF << parts << endl;
    parts = strtok(NULL, "\n\r");
  }
  
  fileARFF << endl << RELATION_ARFF << CUOTE_ARFF << nameRelation->Out() << CUOTE_ARFF << endl << endl;
  if (PRINT_OUT) 
    cout   << endl << RELATION_ARFF << CUOTE_ARFF << nameRelation->Out() << CUOTE_ARFF << endl << endl;
  
  fileARFF << DOMAIN_ATT_ARFF << endl;
  if (PRINT_OUT) 
    cout  << DOMAIN_ATT_ARFF << endl;
  
  this->listPrattPatterns->SetInitial();
  this->listTypeOfData->SetInitial(); 
  
  while (this->listPrattPatterns->SetNext() && this->listTypeOfData->SetNext()) {
    
    Pratt2Patterns* currentPratt2Patterns = this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->Get(positionInPatternFile - 1);

    int counter          = 0;
    int numberAttributes = (ATTRIBUTE_COMPLETE)?
                           (int) (currentPratt2Patterns->Patterns()->Length()*percentagePattern/100):
                           (int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentagePattern/100);
    
    currentPratt2Patterns->Patterns()->SetInitial();
    while (currentPratt2Patterns->Patterns()->SetNext() && counter++ < numberAttributes) {
      sprintf(buffer, PATTERN_ATT_COM_ARFF, this->listTypeOfData->GetCurrent()->Out(), currentPratt2Patterns->Patterns()->GetCurrent()->Pattern()->Out());
      fileARFF << buffer << endl;
      if (PRINT_OUT) 
        cout   << buffer << endl;
    }

  }  
    
  fileARFF << CLASS_ATT_ARFF << endl;
  if (PRINT_OUT) 
    cout   << CLASS_ATT_ARFF << endl;
  
  fileARFF << endl << DATA_ARFF << endl << endl;
  if (PRINT_OUT) 
    cout   << endl << DATA_ARFF << endl << endl;
  
  this->ligandCathFASTAProfile->ListCathDomainProfile()->SetInitial();
  while (this->ligandCathFASTAProfile->ListCathDomainProfile()->SetNext()) {

    fileARFF << this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();
    if (PRINT_OUT) 
      cout   << this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();

    this->listPrattPatterns->SetInitial();
    this->listTypeOfData->SetInitial();
    
    while (this->listPrattPatterns->SetNext() && this->listTypeOfData->SetNext()) {

      String* currentSequence = NULL;

      if      (*(this->listTypeOfData->GetCurrent()) == "Seq") currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();
      else if (*(this->listTypeOfData->GetCurrent()) == "CH")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassChemical();
      else if (*(this->listTypeOfData->GetCurrent()) == "PH")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassPhysical();
      else if (*(this->listTypeOfData->GetCurrent()) == "SS")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->SecondaryStructureP();
      else if (*(this->listTypeOfData->GetCurrent()) == "MT")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesMT();
      else                                                     currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();

      this->searchPattern->Sequence(currentSequence);

      Pratt2Patterns* currentPratt2Patterns = this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->Get(positionInPatternFile - 1);

      int counter          = 0;
      int numberAttributes = (ATTRIBUTE_COMPLETE)?
                             (int) (currentPratt2Patterns->Patterns()->Length()*percentagePattern/100):
                             (int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentagePattern/100);
      
      currentPratt2Patterns->Patterns()->SetInitial();
      while (currentPratt2Patterns->Patterns()->SetNext() && counter++ < numberAttributes) {

        this->searchPattern->Pattern(currentPratt2Patterns->Patterns()->GetCurrent()->Pattern());
        this->searchPattern->SearchPattern();

        fileARFF << "," << this->searchPattern->Segments()->Length();
        if (PRINT_OUT) 
          cout   << "," << this->searchPattern->Segments()->Length();

      }

    }
  
    fileARFF << VALUE_BIND_ARFF << endl;
    if (PRINT_OUT) 
      cout     << VALUE_BIND_ARFF << endl;

  }
  
  int numberFalseData = ((percentageFalse >= 0 && percentageFalse <= 100)?((int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentageFalse/(100 - percentageFalse))):(abs(percentageFalse)));
  int counterFalse    = 0;
  
  TListE <int>* listPosition  = new TListE <int> ();
  int           numberElemDel = 0;
  
  numberElemDel = this->cathFASTAProfile->ListCathDomainProfile()->Length() - (numberFalseData + this->ligandCathFASTAProfile->ListCathDomainProfile()->Length());
  
  if (numberElemDel < 0) {
    
    fileARFF << "ERROR!" << endl;
    cout     << "ERROR!" << endl;
     
    fileARFF.close();
    
    if (listPosition) delete listPosition;
    
    return false;
    
  }
    
  for (long i = 0; i < this->cathFASTAProfile->ListCathDomainProfile()->Length(); i++) 
    listPosition->Add(new int (i + 1));
  
  for (long i = 0; i < numberElemDel; i++) 
    listPosition->Delete(rand() % listPosition->Length());
  
  listPosition->SetInitial();
  if (!listPosition->SetNext()) {
    
    fileARFF << "ERROR!" << endl;
    cout     << "ERROR!" << endl;
     
    fileARFF.close();
    
    if (listPosition) delete listPosition;
    
    return false;
    
  }
    
  long position = 0;
    
  this->cathFASTAProfile->ListCathDomainProfile()->SetInitial();
  while (this->cathFASTAProfile->ListCathDomainProfile()->SetNext() && counterFalse < numberFalseData) {

    if (*(listPosition->GetCurrent()) != ++position) continue;
    
    CathFASTAProfile* searchCathFASTAProfile = this->ligandCathFASTAProfile->ListCathDomainProfile()->FirstOcurrence(PatternSpace::EqualDomain, this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain());
    
    if (searchCathFASTAProfile) { 
      if (!listPosition->SetNext()) 
        break;
      continue;
    }
    
    if (this->excludeCathFASTAProfile && this->excludeCathFASTAProfile->ListCathDomainProfile()->Length()) {
      
      searchCathFASTAProfile = this->excludeCathFASTAProfile->ListCathDomainProfile()->FirstOcurrence(PatternSpace::EqualDomain, this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain());

      if (searchCathFASTAProfile) { 
        if (!listPosition->SetNext()) 
          break;
        continue;
      }
      
    }
    
    counterFalse++;
    
    fileARFF << this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();
    if (PRINT_OUT) 
      cout   << this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();

    this->listPrattPatterns->SetInitial();
    this->listTypeOfData->SetInitial();
    
    while (this->listPrattPatterns->SetNext() && this->listTypeOfData->SetNext()) {
    
      Pratt2Patterns* currentPratt2Patterns = this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->Get(positionInPatternFile - 1);

      int counter          = 0;
      int numberAttributes = (ATTRIBUTE_COMPLETE)?
                             (int) (currentPratt2Patterns->Patterns()->Length()*percentagePattern/100):
                             (int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentagePattern/100);

      String* currentSequence = NULL;

      if      (*(this->listTypeOfData->GetCurrent()) == "Seq") currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();
      else if (*(this->listTypeOfData->GetCurrent()) == "CH")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassChemical();
      else if (*(this->listTypeOfData->GetCurrent()) == "PH")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassPhysical();
      else if (*(this->listTypeOfData->GetCurrent()) == "SS")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->SecondaryStructureP();
      else if (*(this->listTypeOfData->GetCurrent()) == "MT")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesMT();
      else                                                     currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();

      this->searchPattern->Sequence(currentSequence);

      counter = 0;

      currentPratt2Patterns->Patterns()->SetInitial();
      while (currentPratt2Patterns->Patterns()->SetNext() && counter++ < numberAttributes) {

        this->searchPattern->Pattern(currentPratt2Patterns->Patterns()->GetCurrent()->Pattern());
        this->searchPattern->SearchPattern();

        fileARFF << "," << this->searchPattern->Segments()->Length();
        if (PRINT_OUT) 
          cout   << "," << this->searchPattern->Segments()->Length();

      }
      
    }
    
    fileARFF << VALUE_NBIND_ARFF << endl;
    if (PRINT_OUT) 
      cout   << VALUE_NBIND_ARFF << endl;

    if (!listPosition->SetNext()) break;
    
  }
  
  fileARFF.close();
  
  if (listPosition) delete listPosition;
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool CombinedPatternsCathFASTAProfile::CreateCompleteARFF (String* nameRelation, String* comments, float percentagePattern, float percentageFalse, int positionInList) {

  if (!this->cathFASTAProfile     || !this->ligandCathFASTAProfile        || 
      !this->listPrattPatterns    || !this->listPrattPatterns->Length()   ||
      !this->filenameOut          || !this->filenameOut->Length())
    return false;
  
  ofstream fileARFF (this->filenameOut->Out());
  
  if (!fileARFF.is_open()) return false;
  
  char     buffer [LENGTHLINE + 1];
  char*    parts = NULL;
  
  strcpy (buffer, comments->Out());
  
  parts = strtok(buffer, "\n\r");
  while (parts) {
    fileARFF << COMMENT_ARFF << parts << endl;
    if (PRINT_OUT) 
      cout     << COMMENT_ARFF << parts << endl;
    parts = strtok(NULL, "\n\r");
  }
  
  fileARFF << endl << RELATION_ARFF << CUOTE_ARFF << nameRelation->Out() << CUOTE_ARFF << endl << endl;
  if (PRINT_OUT) 
    cout   << endl << RELATION_ARFF << CUOTE_ARFF << nameRelation->Out() << CUOTE_ARFF << endl << endl;
  
 fileARFF << DOMAIN_ATT_ARFF << endl;
  if (PRINT_OUT) 
    cout  << DOMAIN_ATT_ARFF << endl;
  
  this->listPrattPatterns->Get(positionInList)->ListGroupPrattPatterns()->SetInitial();
  while (this->listPrattPatterns->Get(positionInList)->ListGroupPrattPatterns()->SetNext()) {
    
    Pratt2Patterns* currentPratt2Patterns = this->listPrattPatterns->Get(positionInList)->ListGroupPrattPatterns()->GetCurrent();

    int counter          = 0;
    int numberAttributes = (ATTRIBUTE_COMPLETE)?
                           (int) (currentPratt2Patterns->Patterns()->Length()*percentagePattern/100):
                           (int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentagePattern/100);
    
    currentPratt2Patterns->Patterns()->SetInitial();
    while (currentPratt2Patterns->Patterns()->SetNext() && counter++ < numberAttributes) {
      sprintf(buffer, PATTERN_ATT_ARFF, currentPratt2Patterns->Patterns()->GetCurrent()->Pattern()->Out());
      fileARFF << buffer << endl;
      if (PRINT_OUT) 
        cout   << buffer << endl;
    }

  }  
    
  fileARFF << CLASS_ATT_ARFF << endl;
  if (PRINT_OUT) 
    cout   << CLASS_ATT_ARFF << endl;
  
  fileARFF << endl << DATA_ARFF << endl << endl;
  if (PRINT_OUT) 
    cout   << endl << DATA_ARFF << endl << endl;
  
  this->ligandCathFASTAProfile->ListCathDomainProfile()->SetInitial();
  while (this->ligandCathFASTAProfile->ListCathDomainProfile()->SetNext()) {

    fileARFF << this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();
    if (PRINT_OUT) 
      cout   << this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();

    this->listPrattPatterns->Get(positionInList)->ListGroupPrattPatterns()->SetInitial();
    
    while (this->listPrattPatterns->Get(positionInList)->ListGroupPrattPatterns()->SetNext()) {

      String* currentSequence = NULL;

      if      (*(this->listTypeOfData->Get(positionInList)) == "Seq") currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();
      else if (*(this->listTypeOfData->Get(positionInList)) == "CH")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassChemical();
      else if (*(this->listTypeOfData->Get(positionInList)) == "PH")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassPhysical();
      else if (*(this->listTypeOfData->Get(positionInList)) == "SS")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->SecondaryStructureP();
      else if (*(this->listTypeOfData->Get(positionInList)) == "MT")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesMT();
      else                                                            currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();

      this->searchPattern->Sequence(currentSequence);

      Pratt2Patterns* currentPratt2Patterns = this->listPrattPatterns->Get(positionInList)->ListGroupPrattPatterns()->GetCurrent();

      int counter          = 0;
      int numberAttributes = (ATTRIBUTE_COMPLETE)?
                             (int) (currentPratt2Patterns->Patterns()->Length()*percentagePattern/100):
                             (int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentagePattern/100);
      
      currentPratt2Patterns->Patterns()->SetInitial();
      while (currentPratt2Patterns->Patterns()->SetNext() && counter++ < numberAttributes) {

        this->searchPattern->Pattern(currentPratt2Patterns->Patterns()->GetCurrent()->Pattern());
        this->searchPattern->SearchPattern();

        fileARFF << "," << this->searchPattern->Segments()->Length();
        if (PRINT_OUT) 
          cout   << "," << this->searchPattern->Segments()->Length();

      }

    }
  
    fileARFF << VALUE_BIND_ARFF << endl;
    if (PRINT_OUT) 
      cout     << VALUE_BIND_ARFF << endl;

  }
  
  int numberFalseData = ((percentageFalse >= 0 && percentageFalse <= 100)?((int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentageFalse/(100 - percentageFalse))):(abs(percentageFalse)));
  int counterFalse    = 0;
  
  TListE <int>* listPosition  = new TListE <int> ();
  int           numberElemDel = 0;
  
  numberElemDel = this->cathFASTAProfile->ListCathDomainProfile()->Length() - (numberFalseData + this->ligandCathFASTAProfile->ListCathDomainProfile()->Length());
  
  if (numberElemDel < 0) {
    
    fileARFF << "ERROR!" << endl;
    cout     << "ERROR!" << endl;
     
    fileARFF.close();
    
    if (listPosition) delete listPosition;
    
    return false;
    
  }
    
  for (long i = 0; i < this->cathFASTAProfile->ListCathDomainProfile()->Length(); i++) 
    listPosition->Add(new int (i + 1));
  
  for (long i = 0; i < numberElemDel; i++) 
    listPosition->Delete(rand() % listPosition->Length());
  
  listPosition->SetInitial();
  if (!listPosition->SetNext()) {
    
    fileARFF << "ERROR!" << endl;
    cout     << "ERROR!" << endl;
     
    fileARFF.close();
    
    if (listPosition) delete listPosition;
    
    return false;
    
  }
    
  long position = 0;
    
  this->cathFASTAProfile->ListCathDomainProfile()->SetInitial();
  while (this->cathFASTAProfile->ListCathDomainProfile()->SetNext() && counterFalse < numberFalseData) {

    if (*(listPosition->GetCurrent()) != ++position) continue;
    
    CathFASTAProfile* searchCathFASTAProfile = this->ligandCathFASTAProfile->ListCathDomainProfile()->FirstOcurrence(PatternSpace::EqualDomain, this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain());
    
    if (searchCathFASTAProfile) { 
      if (!listPosition->SetNext()) 
        break;
      continue;
    }
    
    if (this->excludeCathFASTAProfile && this->excludeCathFASTAProfile->ListCathDomainProfile()->Length()) {
      
      searchCathFASTAProfile = this->excludeCathFASTAProfile->ListCathDomainProfile()->FirstOcurrence(PatternSpace::EqualDomain, this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain());

      if (searchCathFASTAProfile) { 
        if (!listPosition->SetNext()) 
          break;
        continue;
      }
      
    }
    
    counterFalse++;
    
    fileARFF << this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();
    if (PRINT_OUT) 
      cout   << this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();

    this->listPrattPatterns->Get(positionInList)->ListGroupPrattPatterns()->SetInitial();
    
    while (this->listPrattPatterns->Get(positionInList)->ListGroupPrattPatterns()->SetNext()) {
    
      Pratt2Patterns* currentPratt2Patterns = this->listPrattPatterns->Get(positionInList)->ListGroupPrattPatterns()->GetCurrent();

      int counter          = 0;
      int numberAttributes = (ATTRIBUTE_COMPLETE)?
                             (int) (currentPratt2Patterns->Patterns()->Length()*percentagePattern/100):
                             (int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentagePattern/100);

      String* currentSequence = NULL;

      if      (*(this->listTypeOfData->Get(positionInList)) == "Seq") currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();
      else if (*(this->listTypeOfData->Get(positionInList)) == "CH")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassChemical();
      else if (*(this->listTypeOfData->Get(positionInList)) == "PH")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassPhysical();
      else if (*(this->listTypeOfData->Get(positionInList)) == "SS")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->SecondaryStructureP();
      else if (*(this->listTypeOfData->Get(positionInList)) == "MT")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesMT();
      else                                                            currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();

      this->searchPattern->Sequence(currentSequence);

      counter = 0;

      currentPratt2Patterns->Patterns()->SetInitial();
      while (currentPratt2Patterns->Patterns()->SetNext() && counter++ < numberAttributes) {

        this->searchPattern->Pattern(currentPratt2Patterns->Patterns()->GetCurrent()->Pattern());
        this->searchPattern->SearchPattern();

        fileARFF << "," << this->searchPattern->Segments()->Length();
        if (PRINT_OUT) 
          cout   << "," << this->searchPattern->Segments()->Length();

      }
      
    }
    
    fileARFF << VALUE_NBIND_ARFF << endl;
    if (PRINT_OUT) 
      cout   << VALUE_NBIND_ARFF << endl;

    if (!listPosition->SetNext()) break;
    
  }
  
  fileARFF.close();
  
  if (listPosition) delete listPosition;
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool CombinedPatternsCathFASTAProfile::CreateCompleteCombinedARFF (String* nameRelation, String* comments, float percentagePattern, float percentageFalse) {

  if (!this->cathFASTAProfile     || !this->ligandCathFASTAProfile        || 
      !this->listPrattPatterns    || !this->listPrattPatterns->Length()   ||
      !this->filenameOut          || !this->filenameOut->Length())
    return false;
  
  ofstream fileARFF (this->filenameOut->Out());
  
  if (!fileARFF.is_open()) return false;
  
  char     buffer [LENGTHLINE + 1];
  char*    parts = NULL;
  
  strcpy (buffer, comments->Out());
  
  parts = strtok(buffer, "\n\r");
  while (parts) {
    fileARFF << COMMENT_ARFF << parts << endl;
    if (PRINT_OUT) 
      cout   << COMMENT_ARFF << parts << endl;
    parts = strtok(NULL, "\n\r");
  }
  
  fileARFF << endl << RELATION_ARFF << CUOTE_ARFF << nameRelation->Out() << CUOTE_ARFF << endl << endl;
  if (PRINT_OUT) 
    cout   << endl << RELATION_ARFF << CUOTE_ARFF << nameRelation->Out() << CUOTE_ARFF << endl << endl;
  
  fileARFF << DOMAIN_ATT_ARFF << endl;
  if (PRINT_OUT) 
    cout  << DOMAIN_ATT_ARFF << endl;
  
  this->listPrattPatterns->SetInitial();
  this->listTypeOfData->SetInitial(); 
  
  while (this->listPrattPatterns->SetNext() && this->listTypeOfData->SetNext()) {
    
    this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->SetInitial();
    
    while (this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->SetNext()) {
      
      Pratt2Patterns* currentPratt2Patterns = this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->GetCurrent();

      int counter          = 0;
      int numberAttributes = (ATTRIBUTE_COMPLETE)?
                             (int) (currentPratt2Patterns->Patterns()->Length()*percentagePattern/100):
                             (int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentagePattern/100);

      currentPratt2Patterns->Patterns()->SetInitial();
      while (currentPratt2Patterns->Patterns()->SetNext() && counter++ < numberAttributes) {
        sprintf(buffer, PATTERN_ATT_COM_ARFF, this->listTypeOfData->GetCurrent()->Out(), currentPratt2Patterns->Patterns()->GetCurrent()->Pattern()->Out());
        fileARFF << buffer << endl;
        if (PRINT_OUT) 
          cout   << buffer << endl;
      }

    }
    
  }  
    
  fileARFF << CLASS_ATT_ARFF << endl;
  if (PRINT_OUT) 
    cout   << CLASS_ATT_ARFF << endl;
  
  fileARFF << endl << DATA_ARFF << endl << endl;
  if (PRINT_OUT) 
    cout   << endl << DATA_ARFF << endl << endl;
  
  this->ligandCathFASTAProfile->ListCathDomainProfile()->SetInitial();
  while (this->ligandCathFASTAProfile->ListCathDomainProfile()->SetNext()) {

    fileARFF << this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();
    if (PRINT_OUT) 
      cout   << this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();

    this->listPrattPatterns->SetInitial();
    this->listTypeOfData->SetInitial();
    
    while (this->listPrattPatterns->SetNext() && this->listTypeOfData->SetNext()) {

      String* currentSequence = NULL;

      if      (*(this->listTypeOfData->GetCurrent()) == "Seq") currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();
      else if (*(this->listTypeOfData->GetCurrent()) == "CH")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassChemical();
      else if (*(this->listTypeOfData->GetCurrent()) == "PH")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassPhysical();
      else if (*(this->listTypeOfData->GetCurrent()) == "SS")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->SecondaryStructureP();
      else if (*(this->listTypeOfData->GetCurrent()) == "MT")  currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesMT();
      else                                                     currentSequence = this->ligandCathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();

      this->searchPattern->Sequence(currentSequence);
      
      this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->SetInitial();

      while (this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->SetNext()) {

        Pratt2Patterns* currentPratt2Patterns = this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->GetCurrent();

        int counter          = 0;
        int numberAttributes = (ATTRIBUTE_COMPLETE)?
                               (int) (currentPratt2Patterns->Patterns()->Length()*percentagePattern/100):
                               (int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentagePattern/100);

        currentPratt2Patterns->Patterns()->SetInitial();
        while (currentPratt2Patterns->Patterns()->SetNext() && counter++ < numberAttributes) {

          this->searchPattern->Pattern(currentPratt2Patterns->Patterns()->GetCurrent()->Pattern());
          this->searchPattern->SearchPattern();

          fileARFF << "," << this->searchPattern->Segments()->Length();
          if (PRINT_OUT) 
            cout   << "," << this->searchPattern->Segments()->Length();

        }

      }

    }
  
    fileARFF << VALUE_BIND_ARFF << endl;
    if (PRINT_OUT) 
      cout     << VALUE_BIND_ARFF << endl;

  }
  
  int numberFalseData = ((percentageFalse >= 0 && percentageFalse <= 100)?((int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentageFalse/(100 - percentageFalse))):(abs(percentageFalse)));
  int counterFalse    = 0;
  
  TListE <int>* listPosition  = new TListE <int> ();
  int           numberElemDel = 0;
  
  numberElemDel = this->cathFASTAProfile->ListCathDomainProfile()->Length() - (numberFalseData + this->ligandCathFASTAProfile->ListCathDomainProfile()->Length());
  
  if (numberElemDel < 0) {
    
    fileARFF << "ERROR!" << endl;
    cout     << "ERROR!" << endl;
     
    fileARFF.close();
    
    if (listPosition) delete listPosition;
    
    return false;
    
  }
    
  for (long i = 0; i < this->cathFASTAProfile->ListCathDomainProfile()->Length(); i++) 
    listPosition->Add(new int (i + 1));
  
  for (long i = 0; i < numberElemDel; i++) 
    listPosition->Delete(rand() % listPosition->Length());
  
  listPosition->SetInitial();
  if (!listPosition->SetNext()) {
    
    fileARFF << "ERROR!" << endl;
    cout     << "ERROR!" << endl;
     
    fileARFF.close();
    
    if (listPosition) delete listPosition;
    
    return false;
    
  }
    
  long position = 0;
    
  this->cathFASTAProfile->ListCathDomainProfile()->SetInitial();
  while (this->cathFASTAProfile->ListCathDomainProfile()->SetNext() && counterFalse < numberFalseData) {

    if (*(listPosition->GetCurrent()) != ++position) continue;
    
    CathFASTAProfile* searchCathFASTAProfile = this->ligandCathFASTAProfile->ListCathDomainProfile()->FirstOcurrence(PatternSpace::EqualDomain, this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain());
    
    if (searchCathFASTAProfile) { 
      if (!listPosition->SetNext()) 
        break;
      continue;
    }
    
    if (this->excludeCathFASTAProfile && this->excludeCathFASTAProfile->ListCathDomainProfile()->Length()) {
      
      searchCathFASTAProfile = this->excludeCathFASTAProfile->ListCathDomainProfile()->FirstOcurrence(PatternSpace::EqualDomain, this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain());

      if (searchCathFASTAProfile) { 
        if (!listPosition->SetNext()) 
          break;
        continue;
      }
      
    }
    
    counterFalse++;
    
    fileARFF << this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();
    if (PRINT_OUT) 
      cout   << this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Domain()->Out();

    this->listPrattPatterns->SetInitial();
    this->listTypeOfData->SetInitial();
    
    while (this->listPrattPatterns->SetNext() && this->listTypeOfData->SetNext()) {
    
      String* currentSequence = NULL;

      if      (*(this->listTypeOfData->GetCurrent()) == "Seq") currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();
      else if (*(this->listTypeOfData->GetCurrent()) == "CH")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassChemical();
      else if (*(this->listTypeOfData->GetCurrent()) == "PH")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesClassPhysical();
      else if (*(this->listTypeOfData->GetCurrent()) == "SS")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->SecondaryStructureP();
      else if (*(this->listTypeOfData->GetCurrent()) == "MT")  currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->ResiduesMT();
      else                                                     currentSequence = this->cathFASTAProfile->ListCathDomainProfile()->GetCurrent()->Sequence();

      this->searchPattern->Sequence(currentSequence);

      this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->SetInitial();

      while (this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->SetNext()) {

        Pratt2Patterns* currentPratt2Patterns = this->listPrattPatterns->GetCurrent()->ListGroupPrattPatterns()->GetCurrent();
        
        int counter          = 0;
        int numberAttributes = (ATTRIBUTE_COMPLETE)?
                               (int) (currentPratt2Patterns->Patterns()->Length()*percentagePattern/100):
                               (int) (this->ligandCathFASTAProfile->ListCathDomainProfile()->Length()*percentagePattern/100);

        counter = 0;

        currentPratt2Patterns->Patterns()->SetInitial();
        while (currentPratt2Patterns->Patterns()->SetNext() && counter++ < numberAttributes) {

          this->searchPattern->Pattern(currentPratt2Patterns->Patterns()->GetCurrent()->Pattern());
          this->searchPattern->SearchPattern();

          fileARFF << "," << this->searchPattern->Segments()->Length();
          if (PRINT_OUT) 
            cout   << "," << this->searchPattern->Segments()->Length();

        }

      }

    }
    
    fileARFF << VALUE_NBIND_ARFF << endl;
    if (PRINT_OUT) 
      cout   << VALUE_NBIND_ARFF << endl;

    if (!listPosition->SetNext()) break;
    
  }
  
  fileARFF.close();
  
  if (listPosition) delete listPosition;
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
CombinedPatternsCathFASTAProfile CombinedPatternsCathFASTAProfile::operator= (const CombinedPatternsCathFASTAProfile& combinedPatternsCathFASTAProfile) {

  PatternsCathFASTAProfile::operator =(combinedPatternsCathFASTAProfile);
  
  *(this->listPrattPatterns)           = *(combinedPatternsCathFASTAProfile.listPrattPatterns);
  *(this->listFilenamePatternsCompact) = *(combinedPatternsCathFASTAProfile.listFilenamePatternsCompact);
  *(this->listTypeOfData)              = *(combinedPatternsCathFASTAProfile.listTypeOfData);

  return *this;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
